﻿using System;
using System.Runtime.Serialization;
using System.Windows.Media;
using System.Windows.Media.Imaging;

using Game.ExtensibleObjects;
using Game.ResourceLocator;
using Game.Types;

namespace Game.Objects
{
    /// <summary>
    /// an instance of an object type (#ObjectType) on the map.
    /// </summary>
    [DataContract(Namespace="game")]
    public class GameObject 
    {
        public event EventHandler<GameObjectEventArgs> PlayerChanged;
        public event EventHandler<GameObjectEventArgs> Changed;
        
        readonly RuntimeExtensionCollection _Extensions;
        GameBuilding _GameBuilding;
        
        [DataMember(Name="ObjectType")]
        public readonly ObjectType _ObjectType;
        
        [DataMember(Name="Building")]
        public string _GameBuildingUrl;
        
        public GameObject()
        {
        }
        
        public GameObject(ObjectType gameType)
            : this(gameType, null)
        {
        }
        
        public GameObject(ObjectType gameType, GameBuilding gameBuilding)
        {
            _ObjectType = gameType;
            _Extensions = new RuntimeExtensionCollection();
            Building = gameBuilding;
            if (gameBuilding != null)
            {
                _GameBuildingUrl = gameBuilding.Url;
            }
        }
        
        [OnDeserialized]
        public void OnDeserialized(StreamingContext c)
        {
            if (_GameBuildingUrl != null)
            {
                object obj = GameResourceLocator.Get(_GameBuildingUrl);
                var t = obj as GameBuilding;
                if (t != null)
                {
                    Building = t;
                }
            }
        }

        public IMapItemType MapItemType 
        {
            get { return _ObjectType; }
        }
        
        public ImageSource Picture 
        {
            get { return _ObjectType.Picture; }
        }
        
        public GameBuilding Building
        {
            get { return _GameBuilding; }
            set 
            {
                if (_GameBuilding != null)
                {
                    _GameBuilding.PlayerChanged -= OnPlayerChanged;
                }

                _GameBuilding = value;

                if (_GameBuilding != null)
                {
                    _GameBuilding.PlayerChanged += OnPlayerChanged;
                }
            }
        }

        public double TerrainCost 
        {
            get { return _ObjectType.TerrainBit.Cost; }
        }

        public RuntimeExtensionCollection Extensions
        {
            get { return _Extensions; }
        }

        void OnPlayerChanged(object source, EventArgs args)
        {
            DoPlayerChanged();
        }
        
        void DoPlayerChanged()
        {
            if (PlayerChanged != null)
            {
                var args = new GameObjectEventArgs(this);
                PlayerChanged(this, args);
            }
        }
        
        public void DoChanged()
        {
            if (Changed != null)
            {
                var args = new GameObjectEventArgs(this);
                Changed(this, args);
            }
        }

        public override string ToString()
        {
            return _ObjectType.Name + "(" + _GameBuildingUrl +")";
        }

    }

    public class GameObjectEventArgs : EventArgs
    {
        readonly GameObject _GameObject;

        public GameObjectEventArgs(GameObject gameObject)
        {
            _GameObject = gameObject;
        }

        public GameObject GameObject
        {
            get { return _GameObject; }
        }
    }

}
